(function ($) {
    let transition = window.mt.transition; // 获取过渡结束事件名; transition兼容解决，transition.js
    /**
     * 1-如果$elem元素隐藏,设置 status = hidden;否则设置 status = shown
     * 2-如果 callback是函数,则执行 callback()函数
     */
    function _common_init($elem, callback) {
        if ($elem.is(':hidden')) $elem.data('status', 'hidden')
        else $elem.data('status', 'shown')
        if (typeof callback === 'function') callback()
        $elem.on('show shown hide hidden', function (e) {
            // console.log('触发了' + e.type + '事件');
            //TODO 自定义扩展功能
        });
    }

    /**
     * 1-如果$elem元素的 status 值为: show 或 shown;直接 return
     * 2-如果$elem元素的 status 值不为: show 或 shown;则设置  status = show;触发 $elem.show事件
     * 3-如果callback是函数,则执行callback()函数
     */
    function _common_show($elem, callback) {
        if ($elem.data('status') === 'show') return;
        if ($elem.data('status') === 'shown') return;
        $elem.data('status', 'show').trigger('show');
        if (typeof callback === 'function') callback();
    }

    /**
     * 1-如果$elem元素的 status 值为: hide 或 hidden;直接 return
     * 2-如果$elem元素的 status 值不为: hide 或 hidden;则设置  status = hide;触发 $elem.hide事件
     * 3-如果callback是函数,则执行callback()函数
     */
    function _common_hide($elem, callback) {
        if ($elem.data('status') === 'hide') return;
        if ($elem.data('status') === 'hidden') return;
        $elem.data('status', 'hide').trigger('hide');
        if (typeof callback === 'function') callback();
    }

    // 正常显示和隐藏
    let silent = {
        init: function ($elem) {
            _common_init($elem)
        },
        show: function ($elem) {
            _common_show($elem, function () {
                $elem.show();
                $elem.data('status', 'shown').trigger('shown');
            });
        },
        hide: function ($elem) {
            _common_hide($elem, function () {
                $elem.hide();
                $elem.data('status', 'hidden').trigger('hidden');
            });

        },
    };
    // 带效果的显示和隐藏，css3实现方法
    let css3 = {
        _css3_common_init: function ($elem, className) {
            $elem.addClass('transition');
            _common_init($elem, function () {
                $elem.addClass(className);
            });
        },
        _css3_common_show: function ($elem, className) {
            _common_show($elem, function () {
                $elem.off(transition.end).one(transition.end, function () {
                    $elem.data('status', 'shown').trigger('shown');
                });
                $elem.show();
                setTimeout(function () {
                    $elem.removeClass(className);
                }, 20);
            });
        },
        _css3_common_hide: function ($elem, className) {
            _common_hide($elem, function () {
                $elem.off(transition.end).one(transition.end, function () {
                    $elem.hide();
                    $elem.data('status', 'hidden').trigger('hidden');
                });
                $elem.addClass(className);
            });
        },
        fade: { // 淡入淡出
            init: function ($elem) {
                css3._css3_common_init($elem, 'fadeOut');
            },
            show: function ($elem) {
                css3._css3_common_show($elem, 'fadeOut');
            },
            hide: function ($elem) {
                css3._css3_common_hide($elem, 'fadeOut');
            }
        },
        slideUpDown: { // 上下滚动
            init: function ($elem) {
                $elem.height($elem.height());
                css3._css3_common_init($elem, 'slideUpDownCollapse');
            },
            show: function ($elem) {
                css3._css3_common_show($elem, 'slideUpDownCollapse');
            },
            hide: function ($elem) {
                css3._css3_common_hide($elem, 'slideUpDownCollapse');
            }
        },
        slideLeftRight: { // 左右滚动
            init: function ($elem) {
                $elem.width($elem.width());
                css3._css3_common_init($elem, 'slideLeftRightCollapse');
            },
            show: function ($elem) {
                css3._css3_common_show($elem, 'slideLeftRightCollapse');
            },
            hide: function ($elem) {
                css3._css3_common_hide($elem, 'slideLeftRightCollapse');
            }
        },
        fadeSlideUpDown: { // 淡入淡出上下滚动
            init: function ($elem) {
                $elem.height($elem.height());
                css3._css3_common_init($elem, 'fadeOut slideUpDownCollapse');
            },
            show: function ($elem) {
                css3._css3_common_show($elem, 'fadeOut slideUpDownCollapse');
            },
            hide: function ($elem) {
                css3._css3_common_hide($elem, 'fadeOut slideUpDownCollapse');
            }
        },
        fadeSlideLeftRight: { // 淡入淡出左右滚动
            init: function ($elem) {
                $elem.width($elem.width());
                css3._css3_common_init($elem, 'fadeOut slideLeftRightCollapse');
            },
            show: function ($elem) {
                css3._css3_common_show($elem, 'fadeOut slideLeftRightCollapse');
            },
            hide: function ($elem) {
                css3._css3_common_hide($elem, 'fadeOut slideLeftRightCollapse');
            }
        }
    };

    // 带效果的显示和隐藏，js实现方法
    let js = {
        _js_common_init: function ($elem, callback) {
            // js和transition动画冲突,在执行js前;将transition去掉
            $elem.removeClass('transition');
            _common_init($elem, callback);
        },
        _js_common_show: function ($elem, mode) {
            _common_show($elem, function () {
                $elem.stop()[mode](
                    function () {
                        $elem.data('status', 'shown').trigger('shown');
                    }
                );
            });
        },
        _js_common_hide: function ($elem, mode) {
            _common_hide($elem, function () {
                $elem.stop()[mode](function () {
                    $elem.data('status', 'hidden').trigger('hidden');
                });
            });
        },

        _js_customInit: function ($elem, options) {
            let styles = {};
            for (let p in options) {
                styles[p] = $elem.css(p);
            }
            $elem.data('styles', styles);
            js._js_common_init($elem, function () {
                $elem.css(options);
            });
        },
        _js_customShow: function ($elem) {
             $elem.modeShow = function () {
                $elem.show();
                $elem.stop().animate($elem.data('styles'), function () {
                    $elem.data('status', 'shown').trigger('shown');
                });
            }
            js._js_common_show($elem, 'modeShow');
        },
        _js_customHide: function ($elem, options) {
            $elem.modeHide =function () {
                $elem.stop().animate(options, function () {
                    $elem.hide();
                    $elem.data('status', 'hidden').trigger('hidden');
                });
            }
            js._js_common_hide($elem,'modeHide');
        },
        fade: { // 淡入淡出
            init: function ($elem) {
                js._js_common_init($elem);
            },
            show: function ($elem) {
                js._js_common_show($elem, 'fadeIn');
            },
            hide: function ($elem) {
                js._js_common_hide($elem, 'fadeOut');
            }
        },
        slideUpDown: { // 上下滚动
            init: function ($elem) {
                js._js_common_init($elem);
            },
            show: function ($elem) {
                js._js_common_show($elem, 'slideDown');
            },
            hide: function ($elem) {
                js._js_common_hide($elem, 'slideUp');
            }
        },
        slideLeftRight: { // 左右滚动
            init: function ($elem) {
                js._js_customInit($elem, {'width': 0, 'padding-left': 0, 'padding-right': 0});
            },
            show: function ($elem) {
                js._js_customShow($elem);
            },
            hide: function ($elem) {
                js._js_customHide($elem, {'width': 0, 'padding-left': 0, 'padding-right': 0});
            }
        },
        fadeSlideUpDown: { // 淡入淡出上下滚动
            init: function ($elem) {
                js._js_customInit($elem, {'opacity': 0, 'height': 0, 'padding-top': 0, 'padding-bottom': 0});
            },
            show: function ($elem) {
                js._js_customShow($elem);
            },
            hide: function ($elem) {
                js._js_customHide($elem, {'opacity': 0, 'height': 0, 'padding-top': 0, 'padding-bottom': 0});
            }
        },
        fadeSlideLeftRight: { // 淡入淡出左右滚动
            init: function ($elem) {
                js._js_customInit($elem, {'opacity': 0, 'width': 0, 'padding-left': 0, 'padding-right': 0});
            },
            show: function ($elem) {
                js._js_customShow($elem);
            },
            hide: function ($elem) {
                js._js_customHide($elem, {'opacity': 0, 'width': 0, 'padding-left': 0, 'padding-right': 0});
            }
        }
    };
    let defaults = {css3: true, js: false, animation: 'fade'};// fade  slideUpDown  slideLeftRight  fadeSlideUpDown  fadeSlideLeftRight

    function showHide($elem, options) {
        let mode = null;
        // options = $.extend({}, defaults, options);
        if (options.css3 && transition.isSupport) { //css3 transition
            mode = css3[options.animation] || css3[defaults.animation];
        } else if (options.js) { //js animation
            mode = js[options.animation] || js[defaults.animation];
        } else { // no animation
            mode = silent;
        }
        mode.init($elem);
        return {
            show: mode.show,
            hide: mode.hide
        };
    }

    $.fn.extend({
        showHide: function (option) {
            return this.each(function () {
                let $this = $(this),
                    options = $.extend({}, defaults, typeof option === 'object' && option),
                    mode = $this.data('showHide');
                if (!mode) $this.data('showHide', mode = showHide($this, options));
                if (typeof mode[option] === 'function') mode[option]($this);
            });
        }
    });


    // window.mt = window.mt || {};
    // window.mt.showHide = showHide;

})(jQuery);